package pers.xiaojun.boot.security.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import pers.xiaojun.boot.security.pojo.AuthUserDetails;

import java.util.Collections;


/**
 * Security 工具类
 *
 * @author xiaojun
 * @since 2025-10-03
 */
public class SecurityUtils {


    /**
     * 获取当前认证信息
     *
     * @return {@link Authentication}
     */
    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }


    /**
     * 获取当前认证用户
     *
     * @return {@link AuthUserDetails}
     */
    public static AuthUserDetails getUser() {
        Authentication authentication = getAuthentication();
        if (authentication.getPrincipal() instanceof AuthUserDetails) {
            return (AuthUserDetails) authentication.getPrincipal();
        }
        return null;
    }

    /**
     * 获取当前用户id
     *
     * @return 用户id
     */
    public static Long getUserId() {
        AuthUserDetails user = getUser();
        if (user != null) {
            return user.getId();
        }
        return null;
    }

    /**
     * 设置上下文认证信息
     *
     * @param userDetails 用户认证信息
     * @param request     请求体
     */
    public static void setAuthentication(AuthUserDetails userDetails, HttpServletRequest request) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, Collections.emptyList());
        // 设置请求体中的详细信息到认证令牌中
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }

    /**
     * 判断用户是否拥有指定授权范围
     *
     * @param scopes 授权范围
     * @return 是否拥有
     */
    public static boolean hasAnyScopes(String... scopes) {
        AuthUserDetails user = getUser();
        if (user == null) {
            return false;
        }
        return CollUtil.containsAny(user.getScopes(), Lists.newArrayList(scopes));
    }

    /**
     * 从请求头中获取Token
     *
     * @param request     请求
     * @param tokenHeader header 名称
     * @param tokenPrefix token前缀
     * @return token
     */
    public static String extractTokenAuthorization(HttpServletRequest request, String tokenHeader, String tokenPrefix) {
        String token = request.getHeader(tokenHeader);
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        return StrUtil.subAfter(token, tokenPrefix, true);
    }


}
